using System;

using Sce.Pss.HighLevel.GameEngine2D;
using Sce.Pss.HighLevel.GameEngine2D.Base;
using Sce.Pss.HighLevel.Physics2D;

using Sce.Pss.Core;
using Sce.Pss.Core.Environment;
using Sce.Pss.Core.Graphics;
using Sce.Pss.Core.Imaging;
using Sce.Pss.Core.Input;
using System.IO;
using System.Net;
using System.Collections.Generic;

namespace RedSkies
{
	public class CharacterSprite:SpriteUV
	{
		public bool Flying {get; set;}

		public bool IsJumping{get;protected set;}
		public bool IsGoUp{get;protected set;}
		public bool IsFalling{get;protected set;}
		public bool WantToJump{get;protected set;}
		public int JumpingCount{get;protected set;}
		public int Speed {get;set;}	
		private readonly SpriteList parentList;
		protected GravityInstance Gravity{get;set;}
		
		private readonly IWorldMatrix worldMatrix;
		
		public CharacterSprite (bool fly, TextureInfo textureInfo, Vector2 center, IWorldMatrix worldMatrix, int speed, SpriteList parent)
		{
			Quad.S = new Vector2(50,95);
			Position = center;		
			this.worldMatrix = worldMatrix;
			this.Speed = speed;
			this.Flying=fly;
			this.Speed = speed;
			this.parentList = parent;
			Gravity = new GravityInstance(5);				
		}

		public virtual Vector2 UpdatePosition ()
		{
			return Position;
		}
		
		public virtual Rectangle Update()
		{					
			Position = UpdatePosition ();
			
			Rectangle playerRect = this.GetRect();
			
			if (!Flying)
			{
				bool canFalling = CalculateIfPlayerCanFall (playerRect);
			
				UpdatePlayerJumpOrFall (canFalling);			
			}
			
			return this.GetRect();
		}
		
		public virtual void StartFalling()
		{
			this.IsFalling = true;
			this.Gravity.StartGravity(0, this.Position.Y);
		}

		public virtual void StopFalling()
		{
			this.IsFalling = false;
			this.Gravity.StopGravity();
		}
		
		public void ChangeGravity(GravityInstance gc)
		{
			this.Gravity = gc;
		}
		
		public virtual void StartJump()
		{
			if (!IsJumping)
			{
				WantToJump = false;
				IsJumping = true;
				//JumpingCount = 0;
				IsGoUp=true;
				this.Gravity.StartGravity(4, this.Position.Y);
			}
		}
		
		public virtual void StopJumping()
		{
			WantToJump = false;
			IsJumping = false;
			JumpingCount = 0;
			IsGoUp=false;
		}
		
		protected bool WillBeLeftCollision()
		{
			Rectangle playerRect = this.GetRect();
			
			List<byte> listOfElements = this.worldMatrix.GetAllElementsBeetweenGraphicCoordinates((int)playerRect.X-Speed, (int)(playerRect.X-Speed),(int)playerRect.Y+4, (int) (playerRect.Y+playerRect.Height));
			                                                                                      
			foreach (byte element in listOfElements)
			{
				if (element!=0)
				{
					return true;					
				}
			}		
			return false;
		}

		protected virtual bool WillBeRightCollision()
		{
			Rectangle playerRect = this.GetRect();
			List<byte> listOfElements = this.worldMatrix.GetAllElementsBeetweenGraphicCoordinates((int)(playerRect.X+Speed+playerRect.Width), 
			                                     (int)((playerRect.X+Speed+playerRect.Width)),(int)playerRect.Y+4, (int) (playerRect.Y+playerRect.Height));
			                                                                                      
			foreach (byte element in listOfElements)
			{
				if (element!=0)
				{
					return true;					
				}
			}		
			return false;
		}
		
		public virtual void NextJumpUpdate()
		{
			float y = Position.Y;
			Position = CalcNextFallPosition ();
			
			float yNew = Position.Y;
			
			if (y>yNew)
			{
				IsGoUp=false;
			}
		}

		public virtual Vector2 CalcNextFallPosition ()
		{
			int y = (int) Position.Y;
			
			Vector2 newPos = new Vector2(Position.X,  Gravity.CalculateY());
			
			Rectangle rect = worldMatrix.GetHighestSpriteRectangleBetweenGraphixCoordinates((int)Position.X, (int)Position.X, y, (int)newPos.Y);
			
			if (rect.Y>-99)
			{
				return new Vector2(Position.X, rect.Y+rect.Height);
			}
			
			return newPos;			
		}
		
		public virtual void UpdatePlayerJumpOrFall (bool canFalling)
		{
			bool wasPlayerFalling = IsFalling;
			
			if (!IsFalling && canFalling&&!IsGoUp)
			{
				StartFalling();	
			} else if (IsFalling &&!canFalling)
			{
				StopFalling();
			}
			
			if (wasPlayerFalling && !IsFalling)
			{
				StopJumping();
			}
						
			if (!IsJumping && IsFalling)
			{
				Position = CalcNextFallPosition ();
			} else if (WantToJump) {
				StartJump();
			}
			
			if (IsJumping)
			{
				NextJumpUpdate();	
			}
		}	
		
		public void DeleteSprite()
		{
			parentList.RemoveChild(this, true);
		}
		
		protected bool CalculateIfPlayerCanFall (Rectangle playerRect)
		{
			List<byte> listOfElements = this.worldMatrix.GetAllElementsBeetweenGraphicCoordinates((int)playerRect.X, (int)(playerRect.X+playerRect.Width),(int)playerRect.Y-1, (int) (playerRect.Y-1));
			                                                                                      
			foreach (byte element in listOfElements)
			{
				if (element!=0)
				{
					return false;
				}
			}
			return true;
		}		
		
	}
}

